/////////////////////////////////////////////////////////////////////////////
// Name:        MainFrame.cpp
// Purpose:
// Author:      yospaly
// Modified by:
// Created:     11/12/2008 22:04:20
// RCS-ID:
// Copyright:   Copyright (C) 2008, yospaly
// Licence:
/////////////////////////////////////////////////////////////////////////////

// For compilers that support precompilation, includes "wx/wx.h".
#include "wx/wxprec.h"

#ifdef __BORLANDC__
#pragma hdrstop
#endif

#ifndef WX_PRECOMP
#include "wx/wx.h"
#endif

////@begin includes
#include "wx/imaglist.h"
#include "CategoryListBox.h"
#include "PackagesListCtrl.h"
#include "PropertiesNotebook.h"
////@end includes

#include "MainFrame.h"
#include "SettingsDialog.h"
#include "DownloadIniDialog.h"
#include "ApplyDialog.h"
#include "pkgmgr.h"
#include "mounttable.h"
#include "DownloadPkgDialog.h"
#include "MaintainPkgDialog.h"
#include "SetupWizard.h"

#include <wx/dir.h>
#include <wx/aboutdlg.h>

////@begin XPM images
#include "../res/reload.xpm"
#include "../res/markupgrades.xpm"
#include "../res/undo.xpm"
#include "../res/apply.xpm"
#include "../res/settings.xpm"
#include "../res/help.xpm"
#include "../res/install.xpm"
#include "../res/uninstall.xpm"
////@end XPM images
#include "../res/cygwine.xpm"


/*!
 * MainFrame type definition
 */

IMPLEMENT_CLASS( MainFrame, wxFrame )


/*!
 * MainFrame event table definition
 */

BEGIN_EVENT_TABLE( MainFrame, wxFrame )

////@begin MainFrame event table entries
    EVT_MENU( ID_RELOAD_TOOL, MainFrame::OnRELOADTOOLClick )

    EVT_MENU( ID_UNDO_TOOL, MainFrame::OnUNDOTOOLClick )

    EVT_MENU( ID_APPLY_TOOL, MainFrame::OnAPPLYTOOLClick )

    EVT_MENU( ID_SETTINGS_TOOL, MainFrame::OnSETTINGSTOOLClick )

    EVT_MENU( ID_ABOUT_TOOL, MainFrame::OnABOUTTOOLClick )

    EVT_MENU( ID_INSTALL_TOOL, MainFrame::OnINSTALLTOOLClick )

    EVT_MENU( ID_UNINSTALL_TOOL, MainFrame::OnUNINSTALLTOOLClick )

////@end MainFrame event table entries

END_EVENT_TABLE()


/*!
 * MainFrame constructors
 */

MainFrame::MainFrame()
{
    Init();
}

MainFrame::MainFrame( wxWindow* parent, wxWindowID id, const wxString& caption, const wxPoint& pos, const wxSize& size, long style )
{
    Init();
    Create( parent, id, caption, pos, size, style );
}


/*!
 * MainFrame creator
 */

bool MainFrame::Create( wxWindow* parent, wxWindowID id, const wxString& caption, const wxPoint& pos, const wxSize& size, long style )
{
////@begin MainFrame creation
    wxFrame::Create( parent, id, caption, pos, size, style );

    CreateControls();
    Centre();

    if (FindWindow(ID_SPLITTERWINDOW))
        ((wxSplitterWindow*) FindWindow(ID_SPLITTERWINDOW))->SetSashPosition(180);
    if (FindWindow(ID_SPLITTERWINDOW1))
        ((wxSplitterWindow*) FindWindow(ID_SPLITTERWINDOW1))->SetSashPosition(300);
////@end MainFrame creation

	wxIcon icon(_T("CYGWINE_ICON"), wxBITMAP_TYPE_ICO_RESOURCE);
	this->SetIcon(icon);

    return true;
}


/*!
 * MainFrame destructor
 */

MainFrame::~MainFrame()
{
////@begin MainFrame destruction
////@end MainFrame destruction
}


/*!
 * Member initialisation
 */

void MainFrame::Init()
{
////@begin MainFrame member initialisation
    p_toolbar = NULL;
    p_category_listbox = NULL;
    p_packages_listctrl = NULL;
    p_statusbar = NULL;
////@end MainFrame member initialisation
}


/*!
 * Control creation for MainFrame
 */

void MainFrame::CreateControls()
{
////@begin MainFrame content construction
    MainFrame* itemFrame1 = this;

    p_toolbar = CreateToolBar( wxTB_FLAT|wxTB_TEXT, ID_TOOLBAR );
    p_toolbar->SetToolBitmapSize(wxSize(24, 24));
    wxBitmap itemtool3Bitmap(wxNullBitmap);
    wxBitmap itemtool3BitmapDisabled;
    p_toolbar->AddTool(ID_EXIT_TOOL, _("Exit"), itemtool3Bitmap, itemtool3BitmapDisabled, wxITEM_NORMAL, _("Exit Citrus"), wxEmptyString);
    wxBitmap itemtool4Bitmap(itemFrame1->GetBitmapResource(wxT("../res/reload.png")));
    wxBitmap itemtool4BitmapDisabled;
    p_toolbar->AddTool(ID_RELOAD_TOOL, _("Reload"), itemtool4Bitmap, itemtool4BitmapDisabled, wxITEM_NORMAL, _("Reload"), wxEmptyString);
    wxBitmap itemtool5Bitmap(itemFrame1->GetBitmapResource(wxT("../res/markupgrades.png")));
    wxBitmap itemtool5BitmapDisabled;
    p_toolbar->AddTool(ID_MARK_ALL_TOOL, _("Upgrade"), itemtool5Bitmap, itemtool5BitmapDisabled, wxITEM_NORMAL, _("Mark All Upgrades"), wxEmptyString);
    p_toolbar->AddSeparator();
    wxBitmap itemtool7Bitmap(itemFrame1->GetBitmapResource(wxT("../res/undo.png")));
    wxBitmap itemtool7BitmapDisabled;
    p_toolbar->AddTool(ID_UNDO_TOOL, _("Undo All"), itemtool7Bitmap, itemtool7BitmapDisabled, wxITEM_NORMAL, _("Undo All"), wxEmptyString);
    wxBitmap itemtool8Bitmap(itemFrame1->GetBitmapResource(wxT("../res/apply.png")));
    wxBitmap itemtool8BitmapDisabled;
    p_toolbar->AddTool(ID_APPLY_TOOL, _("Apply"), itemtool8Bitmap, itemtool8BitmapDisabled, wxITEM_NORMAL, _("Apply Changes"), wxEmptyString);
    p_toolbar->AddSeparator();
    wxSearchCtrl* itemSearchCtrl10 = new wxSearchCtrl( p_toolbar, ID_SEARCHCTRL, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
    p_toolbar->AddControl(itemSearchCtrl10);
    p_toolbar->AddSeparator();
    wxBitmap itemtool12Bitmap(itemFrame1->GetBitmapResource(wxT("../res/settings.png")));
    wxBitmap itemtool12BitmapDisabled;
    p_toolbar->AddTool(ID_SETTINGS_TOOL, _("Settings"), itemtool12Bitmap, itemtool12BitmapDisabled, wxITEM_NORMAL, _("Citrus Settings"), wxEmptyString);
    wxBitmap itemtool13Bitmap(itemFrame1->GetBitmapResource(wxT("../res/help.png")));
    wxBitmap itemtool13BitmapDisabled;
    p_toolbar->AddTool(ID_ABOUT_TOOL, _("About"), itemtool13Bitmap, itemtool13BitmapDisabled, wxITEM_NORMAL, _("About Citrus"), wxEmptyString);
    p_toolbar->AddSeparator();
    wxBitmap itemtool15Bitmap(itemFrame1->GetBitmapResource(wxT("../res/install.png")));
    wxBitmap itemtool15BitmapDisabled;
    p_toolbar->AddTool(ID_INSTALL_TOOL, _("(Re)Install"), itemtool15Bitmap, itemtool15BitmapDisabled, wxITEM_NORMAL, _("(Re)Install Cygwin"), wxEmptyString);
    wxBitmap itemtool16Bitmap(itemFrame1->GetBitmapResource(wxT("../res/uninstall.png")));
    wxBitmap itemtool16BitmapDisabled;
    p_toolbar->AddTool(ID_UNINSTALL_TOOL, _("Uninstall"), itemtool16Bitmap, itemtool16BitmapDisabled, wxITEM_NORMAL, _("Uninstall Cygwin"), wxEmptyString);
    p_toolbar->Realize();
    itemFrame1->SetToolBar(p_toolbar);

    wxSplitterWindow* itemSplitterWindow17 = new wxSplitterWindow( itemFrame1, ID_SPLITTERWINDOW, wxDefaultPosition, wxSize(100, 100), wxNO_BORDER );
    itemSplitterWindow17->SetMinimumPaneSize(80);

    wxAuiNotebook* itemAuiNotebook18 = new wxAuiNotebook( itemSplitterWindow17, ID_AUINOTEBOOK, wxDefaultPosition, wxDefaultSize, wxAUI_NB_TOP );

    wxArrayString p_category_listboxStrings;
    p_category_listboxStrings.Add(_("ALL"));
    p_category_listboxStrings.Add(_("----------------------"));
    p_category_listboxStrings.Add(_("Available"));
    p_category_listboxStrings.Add(_("Updated"));
    p_category_listboxStrings.Add(_("Outdated"));
    p_category_listboxStrings.Add(_("----------------------"));
    p_category_listboxStrings.Add(_("Mark for Install"));
    p_category_listboxStrings.Add(_("Mark for Reinstall"));
    p_category_listboxStrings.Add(_("Mark for Upgrade"));
    p_category_listboxStrings.Add(_("Mark for Remove"));
    p_category_listboxStrings.Add(_("----------------------"));
    p_category_listbox = new CategoryListBox( itemAuiNotebook18, ID_CATEGORY_LISTBOX, wxDefaultPosition, wxDefaultSize, p_category_listboxStrings, wxLB_SINGLE|wxNO_BORDER );
    p_category_listbox->SetFont(wxFont(10, wxSWISS, wxNORMAL, wxNORMAL, false, wxT("Verdana")));
    itemAuiNotebook18->AddPage(p_category_listbox, _("Packages"), false);

    wxSplitterWindow* itemSplitterWindow20 = new wxSplitterWindow( itemSplitterWindow17, ID_SPLITTERWINDOW1, wxDefaultPosition, wxSize(100, 100), wxNO_BORDER );
    itemSplitterWindow20->SetMinimumPaneSize(0);
    itemSplitterWindow20->SetSashGravity(1);

    p_packages_listctrl = new PackagesListCtrl( itemSplitterWindow20, ID_PACKAGES_LISTCTRL, wxDefaultPosition, wxSize(100, 100), wxLC_REPORT|wxLC_SINGLE_SEL|wxLC_HRULES|wxLC_VRULES );
    p_packages_listctrl->SetFont(wxFont(wxNORMAL_FONT->GetPointSize(), wxSWISS, wxNORMAL, wxNORMAL, false, wxT("Verdana")));
    PropertiesNotebook* itemAuiNotebook22 = new PropertiesNotebook( itemSplitterWindow20, ID_PROPERTIES_NOTEBOOK, wxDefaultPosition, wxDefaultSize, wxAUI_NB_TOP );

    itemSplitterWindow20->SplitHorizontally(p_packages_listctrl, itemAuiNotebook22, 300);
    itemSplitterWindow17->SplitVertically(itemAuiNotebook18, itemSplitterWindow20, 180);

    p_statusbar = new wxStatusBar( itemFrame1, ID_STATUSBAR, wxST_SIZEGRIP|wxNO_BORDER );
    p_statusbar->SetFieldsCount(2);
    itemFrame1->SetStatusBar(p_statusbar);

////@end MainFrame content construction

    for (int i=0; i<p_packages_listctrl->GetColumnCount(); i++) {
    	p_packages_listctrl->SetColumnWidth(i, wxLIST_AUTOSIZE_USEHEADER);
    }
    
    // reload
    wxCommandEvent evt(wxEVT_COMMAND_MENU_SELECTED, ID_RELOAD_TOOL);
    evt.SetEventObject(this);
    this->AddPendingEvent(evt);
}


/*!
 * Should we show tooltips?
 */

bool MainFrame::ShowToolTips()
{
    return true;
}

/*!
 * Get bitmap resources
 */

wxBitmap MainFrame::GetBitmapResource( const wxString& name )
{
    // Bitmap retrieval
////@begin MainFrame bitmap retrieval
    wxUnusedVar(name);
    if (name == _T("../res/reload.png"))
    {
        wxBitmap bitmap(reload_xpm);
        return bitmap;
    }
    else if (name == _T("../res/markupgrades.png"))
    {
        wxBitmap bitmap(markupgrades_xpm);
        return bitmap;
    }
    else if (name == _T("../res/undo.png"))
    {
        wxBitmap bitmap(undo_xpm);
        return bitmap;
    }
    else if (name == _T("../res/apply.png"))
    {
        wxBitmap bitmap(apply_xpm);
        return bitmap;
    }
    else if (name == _T("../res/settings.png"))
    {
        wxBitmap bitmap(settings_xpm);
        return bitmap;
    }
    else if (name == _T("../res/help.png"))
    {
        wxBitmap bitmap(help_xpm);
        return bitmap;
    }
    else if (name == _T("../res/install.png"))
    {
        wxBitmap bitmap(install_xpm);
        return bitmap;
    }
    else if (name == _T("../res/uninstall.png"))
    {
        wxBitmap bitmap(uninstall_xpm);
        return bitmap;
    }
    return wxNullBitmap;
////@end MainFrame bitmap retrieval
}

/*!
 * Get icon resources
 */

wxIcon MainFrame::GetIconResource( const wxString& name )
{
    // Icon retrieval
////@begin MainFrame icon retrieval
    wxUnusedVar(name);
    return wxNullIcon;
////@end MainFrame icon retrieval
}


/*!
 * wxEVT_COMMAND_MENU_SELECTED event handler for ID_RELOAD_TOOL
 */

void MainFrame::OnRELOADTOOLClick( wxCommandEvent& event )
{
    event.Skip();

    MountTable& mt = MountTable::get();
    bool installed = !mt.is_cygwin_installed();

    // TODO: check if cygwin installed
    if (installed) {
    	p_toolbar->EnableTool(ID_UNINSTALL_TOOL, true);
    } else {
    	p_toolbar->EnableTool(ID_UNINSTALL_TOOL, false);
    }

    // p_packages_listctrl-();
    p_category_listbox->ShowCategories();
    // p_sourcecat_listbox->ShowCategories();
    
    p_category_listbox->Select(0);
    
    p_packages_listctrl->reload();
    
    // check if cygwin installed
    if (!installed) {
        int ret = wxMessageBox( _("No Cygwin installation found in current system, do you want to install right now?"),
    			_("Install Cygwin?"), wxICON_QUESTION | wxYES_NO );
    	
    	if (wxYES==ret) {
    	    // emulate click "Install Cygwin" tool button
    	    wxCommandEvent evt(wxEVT_COMMAND_MENU_SELECTED, ID_INSTALL_TOOL);
    	    evt.SetEventObject(this);
    	    ::wxPostEvent(this, evt);
    	} else {
    		return;
        }
    }
    
    /* TODO: feature in 2.0 
    bool is_base_pkgs_installed = IniBuilder::get().is_base_pkgs_installed();
    
    if (!is_base_pkgs_installed) {
    	int ret = wxMessageBox( _("Some of Cygwin Base packages are not installed, you must install them before you can continue."),
    			_("Install Base Packages ?"), wxICON_INFORMATION | wxOK );

    	
    }
    */
}


/*!
 * wxEVT_COMMAND_MENU_SELECTED event handler for ID_SETTINGS_TOOL
 */

void MainFrame::OnSETTINGSTOOLClick( wxCommandEvent& event )
{
    event.Skip();
	SettingsDialog dlg(this);
	dlg.ShowModal();
}


/*!
 * wxEVT_COMMAND_MENU_SELECTED event handler for ID_UNDO_TOOL
 */

void MainFrame::OnUNDOTOOLClick( wxCommandEvent& event )
{
    event.Skip();
    p_packages_listctrl->reload();
}


/*!
 * wxEVT_COMMAND_MENU_SELECTED event handler for ID_APPLY_TOOL
 */

void MainFrame::OnAPPLYTOOLClick( wxCommandEvent& event )
{
    PkgHash& pkg_hash = IniBuilder::get().packages;
    wxArrayString install;
    wxArrayString reinstall;
    wxArrayString upgrade;
    wxArrayString remove;
    
    // check if any cygwin application is running
    const wxString& cygwindll_path = MountTable::get().cygpath(CYGWIN_INFO_CYGWINDLL_PATH);
    
detect_lock:
    const wxArrayString& proc_list = ::get_lock_file_processes(cygwindll_path);
    if ( !proc_list.IsEmpty() ) {
    	wxString msg(_("You MUST close following applications before apply changes : \n\n"));
    	for (int i=0; i<proc_list.GetCount(); i++) {
    		msg.Append(_T("  * "));
    		msg.Append(proc_list[i]);
    		msg.Append(_T("\n"));
    	}
    	
    	msg.Append(_("\nPress \"OK\" after you have close above applications."));
    	
    	int answer = wxMessageBox(msg, _("Conflict"),
    			wxOK | wxCANCEL | wxICON_INFORMATION );
    	
    	if (answer == wxOK) {
    		goto detect_lock;
    	} else {
    		return;
    	}

    }
    
    for (PkgHash::iterator it=pkg_hash.begin(); it!=pkg_hash.end(); it++ ) {
    	switch ( it->second.binary_status ) {
    	case PkgInfo::XINSTALL :
    		install.Add(it->first);
    		break;
    	case PkgInfo::REINSTALL :
    		reinstall.Add(it->first);
    		break;
    	case PkgInfo::UPGRADE :
    		upgrade.Add(it->first);
    		break;
    	case PkgInfo::REMOVE :
    		remove.Add(it->first);
    		break;
    	}
    }
    
    wxString changes;
    
    if ( !install.IsEmpty() ) {
    	changes.Append(_("To be installed:\n"));
    	
    	for ( int i=0; i<install.GetCount(); i++ ) {
    		changes.Append(wxString::Format(_("\t%s\n"), install[i].c_str()) );
    	}
    	
    	changes.Append(_("\n"));
    }
    if ( !reinstall.IsEmpty() ) {
    	changes.Append(_("To be reinstalled:\n"));
    	
    	for ( int i=0; i<reinstall.GetCount(); i++ ) {
    		changes.Append(wxString::Format(_("\t%s\n"), reinstall[i].c_str()) );
    	}
    	
    	changes.Append(_("\n"));
    }
    if ( !upgrade.IsEmpty() ) {
    	changes.Append(_("To be upgraded:\n"));
    	
    	for ( int i=0; i<upgrade.GetCount(); i++ ) {
    		changes.Append(wxString::Format(_("\t%s\n"), upgrade[i].c_str()) );
    	}
    	
    	changes.Append(_("\n"));
    }
    if ( !remove.IsEmpty() ) {
    	changes.Append(_("To be removed:\n"));
    	
    	for ( int i=0; i<remove.GetCount(); i++ ) {
    		changes.Append(wxString::Format(_("\t%s\n"), remove[i].c_str()) );
    	}
    	
    	changes.Append(_("\n"));
    }
    
    if ( install.IsEmpty() && remove.IsEmpty() && reinstall.IsEmpty() && upgrade.IsEmpty() ) {
    	return;
    }
    
    ApplyDialog dlg(this);
    dlg.set_changes(changes);
    
    if ( wxID_OK == dlg.ShowModal() ) {
    	PkgMgr::get().set_install_pkgs(install);
    	PkgMgr::get().set_reinstall_pkgs(reinstall);
    	PkgMgr::get().set_upgrade_pkgs(upgrade);
    	PkgMgr::get().set_remove_pkgs(remove);

    	if ( !install.IsEmpty() || !reinstall.IsEmpty() || !upgrade.IsEmpty() ) {
			// DownloadPkgDialog ddlg(this);
    		DownloadPkgDialog ddlg(this);
			
			// !! NOTE: WE MUST PUT LAUNCH THREAD FUNC HERE, ONLY!!
			// CREATE NEW DIALOG WILL MAKE SYSTEM CLEAR EVENT QUEUE
			// THIS WILL BE A BIG TROUBLE IF YOU WANT TO POST MESSAGE
			// AS SOON AS THE THREAD RUNNING.			
			PkgMgr::get().run_download_task();
			
			if ( wxID_OK != ddlg.ShowModal() ) {
				// TODO: reload ?
				return;
			}
    	}
    	
    	if ( !remove.IsEmpty() || !install.IsEmpty() || !reinstall.IsEmpty() || !upgrade.IsEmpty() ) {
			// DownloadPkgDialog ddlg(this);
			MaintainPkgDialog rdlg(this);
			
			// !! NOTE: WE MUST PUT LAUNCH THREAD FUNC HERE, ONLY!!
			// CREATE NEW DIALOG WILL MAKE SYSTEM CLEAR EVENT QUEUE
			// THIS WILL BE A BIG TROUBLE IF YOU WANT TO POST MESSAGE
			// AS SOON AS THE THREAD RUNNING.
			PkgMgr::get().run_maintain_task();
			
			if ( wxID_OK != rdlg.ShowModal() ) {
				// TODO: reload ?
				return;
			}
    	}
    	
    	// regenerate "etc/installed.db" after made changes
    	
    }
}


/*!
 * wxEVT_COMMAND_MENU_SELECTED event handler for ID_UNINSTALL_TOOL
 */

void MainFrame::OnUNINSTALLTOOLClick( wxCommandEvent& event )
{
    event.Skip();
	wxMessageBox(_("Not yet implemented"), _("Sorry"), wxOK);
}


/*!
 * wxEVT_COMMAND_MENU_SELECTED event handler for ID_INSTALL_TOOL
 */

void MainFrame::OnINSTALLTOOLClick( wxCommandEvent& event )
{
    SetupWizard wizard(this);
    wizard.Run();//Wizard( (wxWizardPage*)wizard.p_rootdir_page);
}


/*!
 * wxEVT_COMMAND_MENU_SELECTED event handler for ID_ABOUT_TOOL
 */

void MainFrame::OnABOUTTOOLClick( wxCommandEvent& event )
{
	wxAboutDialogInfo info;
        info.SetName(_("Citrus (Cygwin Installation Tool for Rescuing USers)"));
        info.SetVersion(_("1.0 RC"));
	info.SetDescription(_("Package manager for the Cygwin Linux-like environment, \n"
			"make package installation, removal and upgrade more easy."));
	info.SetCopyright(_T("(C) 2009 Yospaly <yospaly@gmail.com>, GPL v2"));
	
	// info.AddDeveloper(_("Yospaly"));
	info.SetIcon(wxIcon(cygwine_xpm));
	
	info.AddArtist(_T("Redhat inc."));
	info.AddArtist(_T("Chris Faylor"));
	info.AddArtist(_T("DJ Delorie"));
	info.AddArtist(_T("Corinna Vinschen"));
	info.AddArtist(_T("Robert Collins"));
	info.AddArtist(_T("Pavel Tsekov"));
	info.AddArtist(_T("Gary R. Van Sickle"));
	info.AddArtist(_T("John Marshall"));
	info.AddArtist(_T("Ton van Overbeek"));
	info.AddArtist(_T("Michael A Chase"));
	info.AddArtist(_T("Jason Tishler"));
	info.AddArtist(_T("Jan Nieuwenhuizen"));
	info.AddArtist(_T("Brian Keener"));
	info.AddArtist(_T("Gareth Pearce"));
	info.AddArtist(_T("Charles Wilson"));
	info.AddArtist(_T("Matt Hargett"));
	info.AddArtist(_T("Trevor Forbes"));
	info.AddArtist(_T("Ralf Habacker"));
	info.AddArtist(_T("Chris Abbey"));
	info.AddArtist(_T("Earnie Boyd"));
	info.AddArtist(_T("Egor Duda"));
	info.AddArtist(_T("Jeffrey Juliano"));
	info.AddArtist(_T("Andrej Borsenkow"));
	info.AddArtist(_T("Norman Vine"));
	info.AddArtist(_T("Jeff Juliano"));
	info.AddArtist(_T("Ron Parker"));
	info.AddArtist(_T("Vadim Egorov"));
	info.AddArtist(_T("Max Bowsher"));
	info.AddArtist(_T("Igor Pechtchanski"));
	info.AddArtist(_T("Frank Richter"));
	info.AddArtist(_T("Brian Dessent"));
	
    info.SetWebSite(_("http://citrus.googlecode.com"));
	
	wxAboutBox(info);
}

